﻿using System.Collections.Generic;
using System.IO;
using System.Diagnostics;
using Microsoft.WindowsAzure.StorageClient;


namespace AMT.Azure.Metrics.Storage
{
	// TODO: consider adding interface to use for verifying StorageMetricsType at compile time
	public class StorageMetricsSerializer<StorageMetricsType>
	{
		/*
		 * 
		 					// Write xml to a temp file
					string tempFile = System.IO.Path.GetTempFileName();
*/

		private const string XML_TO_CSV_XSLT_SIMPLE = 
			@"<xsl:stylesheet version='1.0' xmlns:xsl='http://www.w3.org/1999/XSL/Transform'> 
				<xsl:output method='text' /> 
 
				<xsl:template match='/*/child::*'> 
				<xsl:for-each select='child::*'> 
				<xsl:if test='position() != last()'>'<xsl:value-of select='normalize-space(.)'/>',    </xsl:if> 
				<xsl:if test='position()  = last()'>'<xsl:value-of select='normalize-space(.)'/>'<xsl:text>&#xD;</xsl:text> 
				</xsl:if> 
				</xsl:for-each> 
				</xsl:template> 
 
			</xsl:stylesheet> ";


		private const string XML_TO_CSV_XSLT = 
			@"<xsl:stylesheet version='1.0' xmlns:xsl='http://www.w3.org/1999/XSL/Transform'> 
				  <xsl:output method='text' encoding='utf-8' /> 
 
				  <xsl:param name='delim' select=""','"" /> 
				  <xsl:param name='quote' select=""'&quot;'"" /> 
				  <xsl:param name='break' select=""'&#xA;'"" /> 
 
				  <xsl:template match='/'> 
					<xsl:apply-templates select='projects/project' /> 
				  </xsl:template> 
 
				  <xsl:template match='project'> 
					<xsl:apply-templates /> 
					<xsl:if test='following-sibling::*'> 
					  <xsl:value-of select='$break' /> 
					</xsl:if> 
				  </xsl:template> 
 
				  <xsl:template match='*'> 
					<!-- remove normalize-space() if you want keep white-space at it is -->  
					<xsl:value-of select='concat($quote, normalize-space(), $quote)' /> 
					<xsl:if test='following-sibling::*'> 
					  <xsl:value-of select='$delim' /> 
					</xsl:if> 
				  </xsl:template> 
 
				  <xsl:template match='text()' /> 
			</xsl:stylesheet> ";

		public static void SerializeCsv(string targetFilePath, CloudTableQuery<StorageMetricsType> query, System.IO.FileMode fileMode = FileMode.Append)
		{
			Debug.Assert(null != targetFilePath && 0 < targetFilePath.Length);
			Debug.Assert(null != query);

			FileInfo fi = new FileInfo(targetFilePath);
			Debug.Assert(null != fi.Extension && 0 < fi.Extension.Length);
			Debug.Assert(".csv" == fi.Extension.ToLower());

			// TODO: find or create Csv DataContractSerializer
			// Temp'ly write metrics to xml
			string tempFile = Path.Combine(Path.GetTempPath(), string.Format("{0}.xml", System.Guid.NewGuid().ToString()));
			Debug.WriteLine(string.Format("Temp file for CSV output: {0}", tempFile));

			SerializeXml(tempFile, query, FileMode.CreateNew);

			using (var strm = new FileStream(fi.FullName, fileMode, FileAccess.Write))
			{
				try
				{
					// Xslt reader
					System.Xml.XmlTextReader rdr = new System.Xml.XmlTextReader(new StringReader(XML_TO_CSV_XSLT_SIMPLE));
					// Xml writer
					System.Xml.XmlTextWriter xmlWriter = new System.Xml.XmlTextWriter(strm, System.Text.Encoding.UTF8);

					// Load the temp xml file
					System.Xml.XPath.XPathDocument doc = new System.Xml.XPath.XPathDocument(tempFile);
					// Load the xslt from string
					System.Xml.Xsl.XslCompiledTransform xslt = new System.Xml.Xsl.XslCompiledTransform(true);
					xslt.Load(rdr);

					try
					{
						xslt.Transform(doc, null, xmlWriter);
					}
					finally
					{
						xmlWriter.Close();
						rdr.Close();
					}

				}
				finally
				{
					strm.Close();
				}
			}

			// Delete the temp xml file
			File.Delete(tempFile);
		}


		public static void SerializeJson(string targetFilePath, CloudTableQuery<StorageMetricsType> query, System.IO.FileMode fileMode = FileMode.Append)
		{
			Debug.Assert(null != targetFilePath && 0 < targetFilePath.Length);
			Debug.Assert(null != query);

			FileInfo fi = new FileInfo(targetFilePath);
			Debug.Assert(null != fi.Extension && 0 < fi.Extension.Length);
			Debug.Assert(".json" == fi.Extension.ToLower());

			using (var strm = new FileStream(fi.FullName, fileMode, FileAccess.Write))
			{
				try
				{
					var dcs = new System.Runtime.Serialization.Json.DataContractJsonSerializer(typeof(IEnumerable<StorageMetricsType>));
					dcs.WriteObject(strm, query);
				}
				finally
				{
					strm.Close();
				}
			}
		}


		public static void SerializeXml(string targetFilePath, CloudTableQuery<StorageMetricsType> query, System.IO.FileMode fileMode = FileMode.Append)
		{
			Debug.Assert(null != targetFilePath && 0 < targetFilePath.Length);
			Debug.Assert(null != query);

			FileInfo fi = new FileInfo(targetFilePath);
			Debug.Assert(null != fi.Extension && 0 < fi.Extension.Length);
			Debug.Assert(".xml" == fi.Extension.ToLower());

			using (var strm = new FileStream(fi.FullName, fileMode, FileAccess.Write))
			{
				try
				{
					var dcs = new System.Runtime.Serialization.DataContractSerializer(typeof(IEnumerable<StorageMetricsType>));
					dcs.WriteObject(strm, query);
				}
				finally
				{
					strm.Close();
				}
			}
		}


		private static void TransformToCsv(string targetFile, string sourceXmlFile)
		{

		}
	}

}
